{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "H2avbgsOS_ZI"
   },
   "source": [
    "# AI Data Analysis Agent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "cLgFv4ExTYXM"
   },
   "source": [
    "* An intelligent agent that analyzes datasets using SQL queries and provides insights through natural language processing.\n",
    "* The agent can handle CSV/Excel files, perform statistical analysis, create visualizations, and answer questions about data in plain English.\n",
    "* Features include data preprocessing, automatic chart generation, correlation analysis, and comprehensive data insights.\n",
    "* Users can upload their data files and ask questions like \"What are the top 10 sales by region?\" or \"Show me a trend analysis of monthly revenue.\n",
    "* The agent provides both automated analysis and custom visualization capabilities"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5qZL1mvWWT2K"
   },
   "source": [
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Dhivya-Bharathy/PraisonAI/blob/main/examples/cookbooks/ai_data_analysis_agent.ipynb)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BJWzXHHTT2dz"
   },
   "source": [
    "# Dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "tlT6U7pnT4K8"
   },
   "outputs": [],
   "source": [
    "!pip install praisonai streamlit openai duckdb pandas numpy plotly matplotlib seaborn"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "zRTsSJQHUMcV"
   },
   "source": [
    "# Setup Key"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "lHrm-atdUNre",
    "outputId": "12e4ec2a-beea-442b-b8e0-4cd831ed0e03"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ API key configured!\n",
      "✅ Using model: gpt-5-nano\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "openai_key = \"sk-..\"\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = openai_key\n",
    "model_choice = \"gpt-5-nano\"\n",
    "\n",
    "print(\"✅ API key configured!\")\n",
    "print(f\"✅ Using model: {model_choice}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "kcQMV2ybU3pQ"
   },
   "source": [
    "# Tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "id": "PM5nIMIKU5IT"
   },
   "outputs": [],
   "source": [
    "import plotly.express as px\n",
    "import plotly.graph_objects as go\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from typing import Any\n",
    "\n",
    "class DataVisualizationTool:\n",
    "    def __init__(self):\n",
    "        self.supported_charts = ['bar', 'line', 'scatter', 'histogram', 'box', 'pie', 'heatmap', 'area']\n",
    "\n",
    "    def create_visualization(self, df: pd.DataFrame, chart_type: str, x_column: str, y_column: str = None, title: str = None) -> Any:\n",
    "        \"\"\"Create various types of data visualizations\"\"\"\n",
    "        try:\n",
    "            if chart_type == 'bar':\n",
    "                fig = px.bar(df, x=x_column, y=y_column, title=title, color_discrete_sequence=['#1f77b4'])\n",
    "            elif chart_type == 'line':\n",
    "                fig = px.line(df, x=x_column, y=y_column, title=title, color_discrete_sequence=['#2ca02c'])\n",
    "            elif chart_type == 'scatter':\n",
    "                fig = px.scatter(df, x=x_column, y=y_column, title=title, color_discrete_sequence=['#ff7f0e'])\n",
    "            elif chart_type == 'histogram':\n",
    "                fig = px.histogram(df, x=x_column, title=title, color_discrete_sequence=['#d62728'])\n",
    "            elif chart_type == 'box':\n",
    "                fig = px.box(df, x=x_column, y=y_column, title=title, color_discrete_sequence=['#9467bd'])\n",
    "            elif chart_type == 'pie':\n",
    "                fig = px.pie(df, values=y_column, names=x_column, title=title)\n",
    "            elif chart_type == 'heatmap':\n",
    "                corr_matrix = df.corr()\n",
    "                fig = px.imshow(corr_matrix, title=title, color_continuous_scale='RdBu')\n",
    "            elif chart_type == 'area':\n",
    "                fig = px.area(df, x=x_column, y=y_column, title=title, color_discrete_sequence=['#8c564b'])\n",
    "            else:\n",
    "                return \"Unsupported chart type\"\n",
    "\n",
    "            fig.update_layout(\n",
    "                template=\"plotly_white\",\n",
    "                font=dict(size=12),\n",
    "                margin=dict(l=50, r=50, t=50, b=50)\n",
    "            )\n",
    "            return fig\n",
    "        except Exception as e:\n",
    "            return f\"Error creating visualization: {str(e)}\"\n",
    "\n",
    "# Custom Data Preprocessing Tool\n",
    "import tempfile\n",
    "import csv\n",
    "\n",
    "class DataPreprocessingTool:\n",
    "    def __init__(self):\n",
    "        self.supported_formats = ['.csv', '.xlsx']\n",
    "\n",
    "    def preprocess_file(self, file) -> tuple:\n",
    "        \"\"\"Preprocess uploaded file and return processed data\"\"\"\n",
    "        try:\n",
    "            if file.name.endswith('.csv'):\n",
    "                df = pd.read_csv(file, encoding='utf-8', na_values=['NA', 'N/A', 'missing'])\n",
    "            elif file.name.endswith('.xlsx'):\n",
    "                df = pd.read_excel(file, na_values=['NA', 'N/A', 'missing'])\n",
    "            else:\n",
    "                return None, None, None, \"Unsupported file format\"\n",
    "\n",
    "            # Clean and preprocess data\n",
    "            for col in df.select_dtypes(include=['object']):\n",
    "                df[col] = df[col].astype(str).replace({r'\"': '\"\"'}, regex=True)\n",
    "\n",
    "            # Parse dates and numeric columns\n",
    "            for col in df.columns:\n",
    "                if 'date' in col.lower():\n",
    "                    df[col] = pd.to_datetime(df[col], errors='coerce')\n",
    "                elif df[col].dtype == 'object':\n",
    "                    try:\n",
    "                        df[col] = pd.to_numeric(df[col])\n",
    "                    except (ValueError, TypeError):\n",
    "                        pass\n",
    "\n",
    "            # Create temporary file\n",
    "            with tempfile.NamedTemporaryFile(delete=False, suffix=\".csv\") as temp_file:\n",
    "                temp_path = temp_file.name\n",
    "                df.to_csv(temp_path, index=False, quoting=csv.QUOTE_ALL)\n",
    "\n",
    "            return temp_path, df.columns.tolist(), df, None\n",
    "        except Exception as e:\n",
    "            return None, None, None, f\"Error processing file: {e}\"\n",
    "\n",
    "# Custom Statistical Analysis Tool\n",
    "from typing import Dict, List\n",
    "\n",
    "class StatisticalAnalysisTool:\n",
    "    def __init__(self):\n",
    "        self.analysis_types = ['descriptive', 'correlation', 'outliers', 'trends', 'patterns']\n",
    "\n",
    "    def analyze_data(self, df: pd.DataFrame, analysis_type: str) -> Dict[str, Any]:\n",
    "        \"\"\"Perform statistical analysis on the dataset\"\"\"\n",
    "        try:\n",
    "            results = {}\n",
    "\n",
    "            if analysis_type == 'descriptive':\n",
    "                results['summary'] = df.describe()\n",
    "                results['info'] = {\n",
    "                    'rows': len(df),\n",
    "                    'columns': len(df.columns),\n",
    "                    'missing_values': df.isnull().sum().sum(),\n",
    "                    'duplicates': len(df[df.duplicated()])\n",
    "                }\n",
    "\n",
    "            elif analysis_type == 'correlation':\n",
    "                numeric_df = df.select_dtypes(include=[np.number])\n",
    "                if len(numeric_df.columns) > 1:\n",
    "                    results['correlation_matrix'] = numeric_df.corr()\n",
    "                    results['high_correlations'] = self._find_high_correlations(results['correlation_matrix'])\n",
    "\n",
    "            elif analysis_type == 'outliers':\n",
    "                numeric_df = df.select_dtypes(include=[np.number])\n",
    "                results['outliers'] = self._detect_outliers(numeric_df)\n",
    "\n",
    "            elif analysis_type == 'trends':\n",
    "                date_cols = df.select_dtypes(include=['datetime64']).columns\n",
    "                if len(date_cols) > 0:\n",
    "                    results['time_series'] = self._analyze_trends(df, date_cols[0])\n",
    "\n",
    "            return results\n",
    "        except Exception as e:\n",
    "            return {'error': f\"Analysis error: {str(e)}\"}\n",
    "\n",
    "    def _find_high_correlations(self, corr_matrix: pd.DataFrame, threshold: float = 0.7) -> List[tuple]:\n",
    "        \"\"\"Find highly correlated variable pairs\"\"\"\n",
    "        high_corr = []\n",
    "        for i in range(len(corr_matrix.columns)):\n",
    "            for j in range(i+1, len(corr_matrix.columns)):\n",
    "                if abs(corr_matrix.iloc[i, j]) > threshold:\n",
    "                    high_corr.append((corr_matrix.columns[i], corr_matrix.columns[j], corr_matrix.iloc[i, j]))\n",
    "        return high_corr\n",
    "\n",
    "    def _detect_outliers(self, df: pd.DataFrame) -> Dict[str, List[int]]:\n",
    "        \"\"\"Detect outliers using IQR method\"\"\"\n",
    "        outliers = {}\n",
    "        for col in df.columns:\n",
    "            Q1 = df[col].quantile(0.25)\n",
    "            Q3 = df[col].quantile(0.75)\n",
    "            IQR = Q3 - Q1\n",
    "            outlier_indices = df[(df[col] < Q1 - 1.5*IQR) | (df[col] > Q3 + 1.5*IQR)].index.tolist()\n",
    "            if outlier_indices:\n",
    "                outliers[col] = outlier_indices\n",
    "        return outliers\n",
    "\n",
    "    def _analyze_trends(self, df: pd.DataFrame, date_col: str) -> Dict[str, Any]:\n",
    "        \"\"\"Analyze time series trends\"\"\"\n",
    "        df_sorted = df.sort_values(date_col)\n",
    "        numeric_cols = df.select_dtypes(include=[np.number]).columns\n",
    "\n",
    "        trends = {}\n",
    "        for col in numeric_cols:\n",
    "            if col != date_col:\n",
    "                # Simple trend analysis\n",
    "                values = df_sorted[col].dropna()\n",
    "                if len(values) > 1:\n",
    "                    trend = np.polyfit(range(len(values)), values, 1)[0]\n",
    "                    trends[col] = {\n",
    "                        'trend_direction': 'increasing' if trend > 0 else 'decreasing',\n",
    "                        'trend_strength': abs(trend),\n",
    "                        'mean': values.mean(),\n",
    "                        'std': values.std()\n",
    "                    }\n",
    "        return trends"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1EiQ1f29U--v"
   },
   "source": [
    "# YAML Prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "QCD5T2nmVANY",
    "outputId": "78b3dbff-f95c-4d37-ef8b-9800ef709593"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ YAML Prompt configured!\n"
     ]
    }
   ],
   "source": [
    "# YAML Prompt\n",
    "yaml_prompt = \"\"\"\n",
    "name: \"AI Data Analysis Agent\"\n",
    "description: \"Expert data analyst with SQL and visualization capabilities\"\n",
    "instructions:\n",
    "  - \"You are an expert data analyst with deep knowledge of statistics, SQL, and data visualization\"\n",
    "  - \"Analyze user queries and provide comprehensive insights about their data\"\n",
    "  - \"Generate appropriate SQL queries when needed for data analysis\"\n",
    "  - \"Suggest relevant visualizations based on data types and analysis goals\"\n",
    "  - \"Provide actionable insights and recommendations based on data patterns\"\n",
    "  - \"Always explain your analysis process and findings clearly\"\n",
    "  - \"Use markdown formatting for better readability\"\n",
    "  - \"Include statistical significance when applicable\"\n",
    "  - \"Highlight any data quality issues or anomalies discovered\"\n",
    "  - \"Focus on practical business insights and actionable recommendations\"\n",
    "\n",
    "tools:\n",
    "  - name: \"DataVisualizationTool\"\n",
    "    description: \"Creates various types of data visualizations including bar, line, scatter, histogram, box, pie, heatmap, and area charts\"\n",
    "  - name: \"DataPreprocessingTool\"\n",
    "    description: \"Handles file upload, data cleaning, type conversion, and preprocessing for analysis\"\n",
    "  - name: \"StatisticalAnalysisTool\"\n",
    "    description: \"Performs descriptive statistics, correlation analysis, outlier detection, and trend analysis\"\n",
    "\n",
    "output_format:\n",
    "  - \"Provide clear, structured analysis results\"\n",
    "  - \"Include relevant visualizations when appropriate\"\n",
    "  - \"Summarize key findings and insights\"\n",
    "  - \"Suggest follow-up analyses if relevant\"\n",
    "  - \"Highlight any data quality concerns\"\n",
    "  - \"Use bullet points and tables for better organization\"\n",
    "\n",
    "temperature: 0.3\n",
    "max_tokens: 4000\n",
    "model: \"gpt-5-nano\"\n",
    "\"\"\"\n",
    "\n",
    "print(\"✅ YAML Prompt configured!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "X83l2PUoVZ5f"
   },
   "source": [
    "# Main"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "r-0OMjXKVbji",
    "outputId": "11822998-a950-4280-b9d0-23a4699b8237"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "📊 AI Data Analysis Agent\n",
      "Intelligent data analysis powered by AI - Upload your data and ask questions in natural language!\n",
      "\n",
      "📁 Upload Your Data\n",
      "Please upload a CSV or Excel file:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "     <input type=\"file\" id=\"files-093651f6-80e9-4a24-9dc8-00e830a2a009\" name=\"files[]\" multiple disabled\n",
       "        style=\"border:none\" />\n",
       "     <output id=\"result-093651f6-80e9-4a24-9dc8-00e830a2a009\">\n",
       "      Upload widget is only available when the cell has been executed in the\n",
       "      current browser session. Please rerun this cell to enable.\n",
       "      </output>\n",
       "      <script>// Copyright 2017 Google LLC\n",
       "//\n",
       "// Licensed under the Apache License, Version 2.0 (the \"License\");\n",
       "// you may not use this file except in compliance with the License.\n",
       "// You may obtain a copy of the License at\n",
       "//\n",
       "//      http://www.apache.org/licenses/LICENSE-2.0\n",
       "//\n",
       "// Unless required by applicable law or agreed to in writing, software\n",
       "// distributed under the License is distributed on an \"AS IS\" BASIS,\n",
       "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
       "// See the License for the specific language governing permissions and\n",
       "// limitations under the License.\n",
       "\n",
       "/**\n",
       " * @fileoverview Helpers for google.colab Python module.\n",
       " */\n",
       "(function(scope) {\n",
       "function span(text, styleAttributes = {}) {\n",
       "  const element = document.createElement('span');\n",
       "  element.textContent = text;\n",
       "  for (const key of Object.keys(styleAttributes)) {\n",
       "    element.style[key] = styleAttributes[key];\n",
       "  }\n",
       "  return element;\n",
       "}\n",
       "\n",
       "// Max number of bytes which will be uploaded at a time.\n",
       "const MAX_PAYLOAD_SIZE = 100 * 1024;\n",
       "\n",
       "function _uploadFiles(inputId, outputId) {\n",
       "  const steps = uploadFilesStep(inputId, outputId);\n",
       "  const outputElement = document.getElementById(outputId);\n",
       "  // Cache steps on the outputElement to make it available for the next call\n",
       "  // to uploadFilesContinue from Python.\n",
       "  outputElement.steps = steps;\n",
       "\n",
       "  return _uploadFilesContinue(outputId);\n",
       "}\n",
       "\n",
       "// This is roughly an async generator (not supported in the browser yet),\n",
       "// where there are multiple asynchronous steps and the Python side is going\n",
       "// to poll for completion of each step.\n",
       "// This uses a Promise to block the python side on completion of each step,\n",
       "// then passes the result of the previous step as the input to the next step.\n",
       "function _uploadFilesContinue(outputId) {\n",
       "  const outputElement = document.getElementById(outputId);\n",
       "  const steps = outputElement.steps;\n",
       "\n",
       "  const next = steps.next(outputElement.lastPromiseValue);\n",
       "  return Promise.resolve(next.value.promise).then((value) => {\n",
       "    // Cache the last promise value to make it available to the next\n",
       "    // step of the generator.\n",
       "    outputElement.lastPromiseValue = value;\n",
       "    return next.value.response;\n",
       "  });\n",
       "}\n",
       "\n",
       "/**\n",
       " * Generator function which is called between each async step of the upload\n",
       " * process.\n",
       " * @param {string} inputId Element ID of the input file picker element.\n",
       " * @param {string} outputId Element ID of the output display.\n",
       " * @return {!Iterable<!Object>} Iterable of next steps.\n",
       " */\n",
       "function* uploadFilesStep(inputId, outputId) {\n",
       "  const inputElement = document.getElementById(inputId);\n",
       "  inputElement.disabled = false;\n",
       "\n",
       "  const outputElement = document.getElementById(outputId);\n",
       "  outputElement.innerHTML = '';\n",
       "\n",
       "  const pickedPromise = new Promise((resolve) => {\n",
       "    inputElement.addEventListener('change', (e) => {\n",
       "      resolve(e.target.files);\n",
       "    });\n",
       "  });\n",
       "\n",
       "  const cancel = document.createElement('button');\n",
       "  inputElement.parentElement.appendChild(cancel);\n",
       "  cancel.textContent = 'Cancel upload';\n",
       "  const cancelPromise = new Promise((resolve) => {\n",
       "    cancel.onclick = () => {\n",
       "      resolve(null);\n",
       "    };\n",
       "  });\n",
       "\n",
       "  // Wait for the user to pick the files.\n",
       "  const files = yield {\n",
       "    promise: Promise.race([pickedPromise, cancelPromise]),\n",
       "    response: {\n",
       "      action: 'starting',\n",
       "    }\n",
       "  };\n",
       "\n",
       "  cancel.remove();\n",
       "\n",
       "  // Disable the input element since further picks are not allowed.\n",
       "  inputElement.disabled = true;\n",
       "\n",
       "  if (!files) {\n",
       "    return {\n",
       "      response: {\n",
       "        action: 'complete',\n",
       "      }\n",
       "    };\n",
       "  }\n",
       "\n",
       "  for (const file of files) {\n",
       "    const li = document.createElement('li');\n",
       "    li.append(span(file.name, {fontWeight: 'bold'}));\n",
       "    li.append(span(\n",
       "        `(${file.type || 'n/a'}) - ${file.size} bytes, ` +\n",
       "        `last modified: ${\n",
       "            file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() :\n",
       "                                    'n/a'} - `));\n",
       "    const percent = span('0% done');\n",
       "    li.appendChild(percent);\n",
       "\n",
       "    outputElement.appendChild(li);\n",
       "\n",
       "    const fileDataPromise = new Promise((resolve) => {\n",
       "      const reader = new FileReader();\n",
       "      reader.onload = (e) => {\n",
       "        resolve(e.target.result);\n",
       "      };\n",
       "      reader.readAsArrayBuffer(file);\n",
       "    });\n",
       "    // Wait for the data to be ready.\n",
       "    let fileData = yield {\n",
       "      promise: fileDataPromise,\n",
       "      response: {\n",
       "        action: 'continue',\n",
       "      }\n",
       "    };\n",
       "\n",
       "    // Use a chunked sending to avoid message size limits. See b/62115660.\n",
       "    let position = 0;\n",
       "    do {\n",
       "      const length = Math.min(fileData.byteLength - position, MAX_PAYLOAD_SIZE);\n",
       "      const chunk = new Uint8Array(fileData, position, length);\n",
       "      position += length;\n",
       "\n",
       "      const base64 = btoa(String.fromCharCode.apply(null, chunk));\n",
       "      yield {\n",
       "        response: {\n",
       "          action: 'append',\n",
       "          file: file.name,\n",
       "          data: base64,\n",
       "        },\n",
       "      };\n",
       "\n",
       "      let percentDone = fileData.byteLength === 0 ?\n",
       "          100 :\n",
       "          Math.round((position / fileData.byteLength) * 100);\n",
       "      percent.textContent = `${percentDone}% done`;\n",
       "\n",
       "    } while (position < fileData.byteLength);\n",
       "  }\n",
       "\n",
       "  // All done.\n",
       "  yield {\n",
       "    response: {\n",
       "      action: 'complete',\n",
       "    }\n",
       "  };\n",
       "}\n",
       "\n",
       "scope.google = scope.google || {};\n",
       "scope.google.colab = scope.google.colab || {};\n",
       "scope.google.colab._files = {\n",
       "  _uploadFiles,\n",
       "  _uploadFilesContinue,\n",
       "};\n",
       "})(self);\n",
       "</script> "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saving customers-100.csv to customers-100.csv\n",
      "\n",
      "📊 Dataset Information:\n",
      "- Rows: 100\n",
      "- Columns: 12\n",
      "- Data Types: 3\n",
      "\n",
      "📋 Data Preview:\n",
      "   Index      Customer Id First Name  Last Name  \\\n",
      "0      1  DD37Cf93aecA6Dc     Sheryl     Baxter   \n",
      "1      2  1Ef7b82A4CAAD10    Preston     Lozano   \n",
      "2      3  6F94879bDAfE5a6        Roy      Berry   \n",
      "3      4  5Cef8BFA16c5e3c      Linda      Olsen   \n",
      "4      5  053d585Ab6b3159     Joanna     Bender   \n",
      "5      6  2d08FB17EE273F4      Aimee      Downs   \n",
      "6      7  EA4d384DfDbBf77     Darren       Peck   \n",
      "7      8  0e04AFde9f225dE      Brett     Mullen   \n",
      "8      9  C2dE4dEEc489ae0     Sheryl     Meyers   \n",
      "9     10  8C2811a503C7c5a   Michelle  Gallagher   \n",
      "\n",
      "                           Company               City  \\\n",
      "0                  Rasmussen Group       East Leonard   \n",
      "1                      Vega-Gentry  East Jimmychester   \n",
      "2                    Murillo-Perry      Isabelborough   \n",
      "3  Dominguez, Mcmillan and Donovan         Bensonview   \n",
      "4         Martin, Lang and Andrade     West Priscilla   \n",
      "5                     Steele Group      Chavezborough   \n",
      "6     Lester, Woodard and Mitchell           Lake Ana   \n",
      "7     Sanford, Davenport and Giles            Kimport   \n",
      "8                   Browning-Simon       Robersonstad   \n",
      "9                     Beck-Hendrix         Elaineberg   \n",
      "\n",
      "                      Country                 Phone 1                Phone 2  \\\n",
      "0                       Chile            229.077.5154       397.884.0519x718   \n",
      "1                    Djibouti              5153435776       686-620-1820x944   \n",
      "2         Antigua and Barbuda         +1-539-402-0259    (496)978-3969x58947   \n",
      "3          Dominican Republic  001-808-617-6467x12895        +1-813-324-8756   \n",
      "4  Slovakia (Slovak Republic)  001-234-203-0635x76146  001-199-446-3860x3486   \n",
      "5      Bosnia and Herzegovina     (283)437-3886x88321           999-728-1637   \n",
      "6            Pitcairn Islands      (496)452-6181x3291   +1-247-266-0963x4995   \n",
      "7                    Bulgaria    001-583-352-7197x297       001-333-145-0369   \n",
      "8                      Cyprus       854-138-4911x5772    +1-448-910-2276x729   \n",
      "9                 Timor-Leste        739.218.2516x459   001-054-401-0347x617   \n",
      "\n",
      "                         Email Subscription Date                      Website  \n",
      "0     zunigavanessa@smith.info        2020-08-24   http://www.stephenson.com/  \n",
      "1              vmata@colon.com        2021-04-23        http://www.hobbs.com/  \n",
      "2          beckycarr@hogan.com        2020-03-25     http://www.lawrence.com/  \n",
      "3  stanleyblackwell@benson.org        2020-06-02   http://www.good-lyons.com/  \n",
      "4      colinalvarado@miles.net        2021-04-17  https://goodwin-ingram.com/  \n",
      "5          louis27@gilbert.com        2020-02-25       http://www.berger.net/  \n",
      "6          tgates@cantrell.com        2021-08-24          https://www.le.com/  \n",
      "7              asnow@colon.com        2021-04-12  https://hammond-ramsey.com/  \n",
      "8      mariokhan@ryan-pope.org        2020-01-13     https://www.bullock.net/  \n",
      "9            mdyer@escobar.net        2021-11-08           https://arias.com/  \n",
      "\n",
      "�� Column Information:\n",
      "                              Column       Data Type  Non-Null Count  \\\n",
      "Index                          Index           int64             100   \n",
      "Customer Id              Customer Id          object             100   \n",
      "First Name                First Name          object             100   \n",
      "Last Name                  Last Name          object             100   \n",
      "Company                      Company          object             100   \n",
      "City                            City          object             100   \n",
      "Country                      Country          object             100   \n",
      "Phone 1                      Phone 1          object             100   \n",
      "Phone 2                      Phone 2          object             100   \n",
      "Email                          Email          object             100   \n",
      "Subscription Date  Subscription Date  datetime64[ns]             100   \n",
      "Website                      Website          object             100   \n",
      "\n",
      "                   Null Count  Unique Values  \n",
      "Index                       0            100  \n",
      "Customer Id                 0            100  \n",
      "First Name                  0             93  \n",
      "Last Name                   0             97  \n",
      "Company                     0             99  \n",
      "City                        0            100  \n",
      "Country                     0             85  \n",
      "Phone 1                     0            100  \n",
      "Phone 2                     0            100  \n",
      "Email                       0            100  \n",
      "Subscription Date           0             96  \n",
      "Website                     0            100  \n",
      "\n",
      "🔍 Data Analysis\n",
      "Available analysis options:\n",
      "1. Quick Insights\n",
      "2. Auto Visualizations\n",
      "3. Custom Analysis\n",
      "\n",
      "�� Quick Insights:\n",
      "📊 Dataset Overview:\n",
      "- Total records: 100\n",
      "- Complete records: 100\n",
      "- Duplicate records: 0\n",
      "- Missing values: 0\n",
      "⚠️ Potential Outliers Detected:\n",
      "- outliers: 0 outliers\n",
      "\n",
      "📈 Auto-Generated Visualizations:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<html>\n",
       "<head><meta charset=\"utf-8\" /></head>\n",
       "<body>\n",
       "    <div>            <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_SVG\"></script><script type=\"text/javascript\">if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}</script>                <script type=\"text/javascript\">window.PlotlyConfig = {MathJaxConfig: 'local'};</script>\n",
       "        <script charset=\"utf-8\" src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>                <div id=\"343e9492-5a62-4f39-9406-4bb6086f2652\" class=\"plotly-graph-div\" style=\"height:525px; width:100%;\"></div>            <script type=\"text/javascript\">                                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById(\"343e9492-5a62-4f39-9406-4bb6086f2652\")) {                    Plotly.newPlot(                        \"343e9492-5a62-4f39-9406-4bb6086f2652\",                        [{\"alignmentgroup\":\"True\",\"bingroup\":\"x\",\"hovertemplate\":\"Index=%{x}\\u003cbr\\u003ecount=%{y}\\u003cextra\\u003e\\u003c\\u002fextra\\u003e\",\"legendgroup\":\"\",\"marker\":{\"color\":\"#d62728\",\"pattern\":{\"shape\":\"\"}},\"name\":\"\",\"offsetgroup\":\"\",\"orientation\":\"v\",\"showlegend\":false,\"x\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],\"xaxis\":\"x\",\"yaxis\":\"y\",\"type\":\"histogram\"}],                        {\"template\":{\"data\":{\"barpolar\":[{\"marker\":{\"line\":{\"color\":\"white\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"barpolar\"}],\"bar\":[{\"error_x\":{\"color\":\"#2a3f5f\"},\"error_y\":{\"color\":\"#2a3f5f\"},\"marker\":{\"line\":{\"color\":\"white\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"bar\"}],\"carpet\":[{\"aaxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"#C8D4E3\",\"linecolor\":\"#C8D4E3\",\"minorgridcolor\":\"#C8D4E3\",\"startlinecolor\":\"#2a3f5f\"},\"baxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"#C8D4E3\",\"linecolor\":\"#C8D4E3\",\"minorgridcolor\":\"#C8D4E3\",\"startlinecolor\":\"#2a3f5f\"},\"type\":\"carpet\"}],\"choropleth\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"choropleth\"}],\"contourcarpet\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"contourcarpet\"}],\"contour\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"contour\"}],\"heatmapgl\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"heatmapgl\"}],\"heatmap\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"heatmap\"}],\"histogram2dcontour\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"histogram2dcontour\"}],\"histogram2d\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"histogram2d\"}],\"histogram\":[{\"marker\":{\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"histogram\"}],\"mesh3d\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"mesh3d\"}],\"parcoords\":[{\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"parcoords\"}],\"pie\":[{\"automargin\":true,\"type\":\"pie\"}],\"scatter3d\":[{\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatter3d\"}],\"scattercarpet\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattercarpet\"}],\"scattergeo\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattergeo\"}],\"scattergl\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattergl\"}],\"scattermapbox\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattermapbox\"}],\"scatterpolargl\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterpolargl\"}],\"scatterpolar\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterpolar\"}],\"scatter\":[{\"fillpattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2},\"type\":\"scatter\"}],\"scatterternary\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterternary\"}],\"surface\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"surface\"}],\"table\":[{\"cells\":{\"fill\":{\"color\":\"#EBF0F8\"},\"line\":{\"color\":\"white\"}},\"header\":{\"fill\":{\"color\":\"#C8D4E3\"},\"line\":{\"color\":\"white\"}},\"type\":\"table\"}]},\"layout\":{\"annotationdefaults\":{\"arrowcolor\":\"#2a3f5f\",\"arrowhead\":0,\"arrowwidth\":1},\"autotypenumbers\":\"strict\",\"coloraxis\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"colorscale\":{\"diverging\":[[0,\"#8e0152\"],[0.1,\"#c51b7d\"],[0.2,\"#de77ae\"],[0.3,\"#f1b6da\"],[0.4,\"#fde0ef\"],[0.5,\"#f7f7f7\"],[0.6,\"#e6f5d0\"],[0.7,\"#b8e186\"],[0.8,\"#7fbc41\"],[0.9,\"#4d9221\"],[1,\"#276419\"]],\"sequential\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"sequentialminus\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]},\"colorway\":[\"#636efa\",\"#EF553B\",\"#00cc96\",\"#ab63fa\",\"#FFA15A\",\"#19d3f3\",\"#FF6692\",\"#B6E880\",\"#FF97FF\",\"#FECB52\"],\"font\":{\"color\":\"#2a3f5f\"},\"geo\":{\"bgcolor\":\"white\",\"lakecolor\":\"white\",\"landcolor\":\"white\",\"showlakes\":true,\"showland\":true,\"subunitcolor\":\"#C8D4E3\"},\"hoverlabel\":{\"align\":\"left\"},\"hovermode\":\"closest\",\"mapbox\":{\"style\":\"light\"},\"paper_bgcolor\":\"white\",\"plot_bgcolor\":\"white\",\"polar\":{\"angularaxis\":{\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\"},\"bgcolor\":\"white\",\"radialaxis\":{\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\"}},\"scene\":{\"xaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"},\"yaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"},\"zaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"}},\"shapedefaults\":{\"line\":{\"color\":\"#2a3f5f\"}},\"ternary\":{\"aaxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"},\"baxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"},\"bgcolor\":\"white\",\"caxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"}},\"title\":{\"x\":0.05},\"xaxis\":{\"automargin\":true,\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"#EBF0F8\",\"zerolinewidth\":2},\"yaxis\":{\"automargin\":true,\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"#EBF0F8\",\"zerolinewidth\":2}}},\"xaxis\":{\"anchor\":\"y\",\"domain\":[0.0,1.0],\"title\":{\"text\":\"Index\"}},\"yaxis\":{\"anchor\":\"x\",\"domain\":[0.0,1.0],\"title\":{\"text\":\"count\"}},\"legend\":{\"tracegroupgap\":0},\"title\":{\"text\":\"Distribution of Index\"},\"barmode\":\"relative\",\"font\":{\"size\":12},\"margin\":{\"l\":50,\"r\":50,\"t\":50,\"b\":50}},                        {\"responsive\": true}                    ).then(function(){\n",
       "                            \n",
       "var gd = document.getElementById('343e9492-5a62-4f39-9406-4bb6086f2652');\n",
       "var x = new MutationObserver(function (mutations, observer) {{\n",
       "        var display = window.getComputedStyle(gd).display;\n",
       "        if (!display || display === 'none') {{\n",
       "            console.log([gd, 'removed!']);\n",
       "            Plotly.purge(gd);\n",
       "            observer.disconnect();\n",
       "        }}\n",
       "}});\n",
       "\n",
       "// Listen for the removal of the full notebook cells\n",
       "var notebookContainer = gd.closest('#notebook-container');\n",
       "if (notebookContainer) {{\n",
       "    x.observe(notebookContainer, {childList: true});\n",
       "}}\n",
       "\n",
       "// Listen for the clearing of the current output cell\n",
       "var outputEl = gd.closest('.output');\n",
       "if (outputEl) {{\n",
       "    x.observe(outputEl, {childList: true});\n",
       "}}\n",
       "\n",
       "                        })                };                            </script>        </div>\n",
       "</body>\n",
       "</html>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<html>\n",
       "<head><meta charset=\"utf-8\" /></head>\n",
       "<body>\n",
       "    <div>            <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_SVG\"></script><script type=\"text/javascript\">if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}</script>                <script type=\"text/javascript\">window.PlotlyConfig = {MathJaxConfig: 'local'};</script>\n",
       "        <script charset=\"utf-8\" src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>                <div id=\"364038f7-3893-411b-95a7-26a2fa25ab20\" class=\"plotly-graph-div\" style=\"height:525px; width:100%;\"></div>            <script type=\"text/javascript\">                                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById(\"364038f7-3893-411b-95a7-26a2fa25ab20\")) {                    Plotly.newPlot(                        \"364038f7-3893-411b-95a7-26a2fa25ab20\",                        [{\"alignmentgroup\":\"True\",\"hovertemplate\":\"Customer Id=%{x}\\u003cbr\\u003eIndex=%{y}\\u003cextra\\u003e\\u003c\\u002fextra\\u003e\",\"legendgroup\":\"\",\"marker\":{\"color\":\"#1f77b4\",\"pattern\":{\"shape\":\"\"}},\"name\":\"\",\"offsetgroup\":\"\",\"orientation\":\"v\",\"showlegend\":false,\"textposition\":\"auto\",\"x\":[\"DD37Cf93aecA6Dc\",\"1Ef7b82A4CAAD10\",\"6F94879bDAfE5a6\",\"5Cef8BFA16c5e3c\",\"053d585Ab6b3159\",\"2d08FB17EE273F4\",\"EA4d384DfDbBf77\",\"0e04AFde9f225dE\",\"C2dE4dEEc489ae0\",\"8C2811a503C7c5a\",\"216E205d6eBb815\",\"CEDec94deE6d69B\",\"e35426EbDEceaFF\",\"A08A8aF8BE9FaD4\",\"6fEaA1b7cab7B6C\",\"8cad0b4CBceaeec\",\"a5DC21AE3a21eaA\",\"F8Aa9d6DfcBeeF8\",\"F160f5Db3EfE973\",\"0F60FF3DdCd7aB0\",\"9F9AdB7B8A6f7F2\",\"FBd0Ded4F02a742\",\"2FB0FAA1d429421\",\"010468dAA11382c\",\"eC1927Ca84E033e\",\"09D7D7C8Fe09aea\",\"aBdfcF2c50b0bfD\",\"b92EBfdF8a3f0E6\",\"3B5dAAFA41AFa22\",\"EDA69ca7a6e96a2\",\"64DCcDFaB9DFd4e\",\"679c6c83DD872d6\",\"7Ce381e4Afa4ba9\",\"A09AEc6E3bF70eE\",\"aA9BAFfBc3710fe\",\"E11dfb2DB8C9f72\",\"889eCf90f68c5Da\",\"7a1Ee69F4fF4B4D\",\"dca4f1D0A0fc5c9\",\"17aD8e2dB3df03D\",\"2f79Cd309624Abb\",\"6e5ad5a5e2bB5Ca\",\"7E441b6B228DBcA\",\"D3fC11A9C235Dc6\",\"30Dfa48fe5Ede78\",\"fD780ED8dbEae7B\",\"300A40d3ce24bBA\",\"283DFCD0Dba40aF\",\"F4Fc91fEAEad286\",\"80F33Fd2AcebF05\",\"Aa20BDe68eAb0e9\",\"e898eEB1B9FE22b\",\"faCEF517ae7D8eB\",\"c09952De6Cda8aA\",\"f3BEf3Be028166f\",\"C6F2Fc6a7948a4e\",\"c8FE57cBBdCDcb2\",\"B5acdFC982124F2\",\"8c7DdF10798bCC3\",\"C681dDd0cc422f7\",\"a940cE42e035F28\",\"9Cf5E6AFE0aeBfd\",\"aEcbe5365BbC67D\",\"FCBdfCEAe20A8Dc\",\"636cBF0835E10ff\",\"fF1b6c9E8Fbf1ff\",\"2A13F74EAa7DA6c\",\"a014Ec1b9FccC1E\",\"421a109cABDf5fa\",\"CC68FD1D3Bbbf22\",\"CBCd2Ac8E3eBDF9\",\"Ef859092FbEcC07\",\"F560f2d3cDFb618\",\"A3F76Be153Df4a3\",\"D01Af0AF7cBbFeA\",\"d40e89dCade7b2F\",\"BF6a1f9bd1bf8DE\",\"FfaeFFbbbf280db\",\"CbAE1d1e9a8dCb1\",\"A7F85c1DE4dB87f\",\"D6CEAfb3BDbaa1A\",\"Ebdb6F6F7c90b69\",\"E8E7e8Cfe516ef0\",\"78C06E9b6B3DF20\",\"03A1E62ADdeb31c\",\"C6763c99d0bd16D\",\"ebe77E5Bf9476CE\",\"E4Bbcd8AD81fC5f\",\"efeb73245CDf1fF\",\"37Ec4B395641c1E\",\"5ef6d3eefdD43bE\",\"98b3aeDcC3B9FF3\",\"aAb6AFc7AfD0fF3\",\"54B5B5Fe9F1B6C5\",\"BE91A0bdcA49Bbc\",\"cb8E23e48d22Eae\",\"CeD220bdAaCfaDf\",\"28CDbC0dFe4b1Db\",\"c23d1D9EE8DEB0A\",\"2354a0E336A91A1\"],\"xaxis\":\"x\",\"y\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],\"yaxis\":\"y\",\"type\":\"bar\"}],                        {\"template\":{\"data\":{\"barpolar\":[{\"marker\":{\"line\":{\"color\":\"white\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"barpolar\"}],\"bar\":[{\"error_x\":{\"color\":\"#2a3f5f\"},\"error_y\":{\"color\":\"#2a3f5f\"},\"marker\":{\"line\":{\"color\":\"white\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"bar\"}],\"carpet\":[{\"aaxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"#C8D4E3\",\"linecolor\":\"#C8D4E3\",\"minorgridcolor\":\"#C8D4E3\",\"startlinecolor\":\"#2a3f5f\"},\"baxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"#C8D4E3\",\"linecolor\":\"#C8D4E3\",\"minorgridcolor\":\"#C8D4E3\",\"startlinecolor\":\"#2a3f5f\"},\"type\":\"carpet\"}],\"choropleth\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"choropleth\"}],\"contourcarpet\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"contourcarpet\"}],\"contour\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"contour\"}],\"heatmapgl\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"heatmapgl\"}],\"heatmap\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"heatmap\"}],\"histogram2dcontour\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"histogram2dcontour\"}],\"histogram2d\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"histogram2d\"}],\"histogram\":[{\"marker\":{\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"histogram\"}],\"mesh3d\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"mesh3d\"}],\"parcoords\":[{\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"parcoords\"}],\"pie\":[{\"automargin\":true,\"type\":\"pie\"}],\"scatter3d\":[{\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatter3d\"}],\"scattercarpet\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattercarpet\"}],\"scattergeo\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattergeo\"}],\"scattergl\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattergl\"}],\"scattermapbox\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattermapbox\"}],\"scatterpolargl\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterpolargl\"}],\"scatterpolar\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterpolar\"}],\"scatter\":[{\"fillpattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2},\"type\":\"scatter\"}],\"scatterternary\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterternary\"}],\"surface\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"surface\"}],\"table\":[{\"cells\":{\"fill\":{\"color\":\"#EBF0F8\"},\"line\":{\"color\":\"white\"}},\"header\":{\"fill\":{\"color\":\"#C8D4E3\"},\"line\":{\"color\":\"white\"}},\"type\":\"table\"}]},\"layout\":{\"annotationdefaults\":{\"arrowcolor\":\"#2a3f5f\",\"arrowhead\":0,\"arrowwidth\":1},\"autotypenumbers\":\"strict\",\"coloraxis\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"colorscale\":{\"diverging\":[[0,\"#8e0152\"],[0.1,\"#c51b7d\"],[0.2,\"#de77ae\"],[0.3,\"#f1b6da\"],[0.4,\"#fde0ef\"],[0.5,\"#f7f7f7\"],[0.6,\"#e6f5d0\"],[0.7,\"#b8e186\"],[0.8,\"#7fbc41\"],[0.9,\"#4d9221\"],[1,\"#276419\"]],\"sequential\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"sequentialminus\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]},\"colorway\":[\"#636efa\",\"#EF553B\",\"#00cc96\",\"#ab63fa\",\"#FFA15A\",\"#19d3f3\",\"#FF6692\",\"#B6E880\",\"#FF97FF\",\"#FECB52\"],\"font\":{\"color\":\"#2a3f5f\"},\"geo\":{\"bgcolor\":\"white\",\"lakecolor\":\"white\",\"landcolor\":\"white\",\"showlakes\":true,\"showland\":true,\"subunitcolor\":\"#C8D4E3\"},\"hoverlabel\":{\"align\":\"left\"},\"hovermode\":\"closest\",\"mapbox\":{\"style\":\"light\"},\"paper_bgcolor\":\"white\",\"plot_bgcolor\":\"white\",\"polar\":{\"angularaxis\":{\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\"},\"bgcolor\":\"white\",\"radialaxis\":{\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\"}},\"scene\":{\"xaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"},\"yaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"},\"zaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"}},\"shapedefaults\":{\"line\":{\"color\":\"#2a3f5f\"}},\"ternary\":{\"aaxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"},\"baxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"},\"bgcolor\":\"white\",\"caxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"}},\"title\":{\"x\":0.05},\"xaxis\":{\"automargin\":true,\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"#EBF0F8\",\"zerolinewidth\":2},\"yaxis\":{\"automargin\":true,\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"#EBF0F8\",\"zerolinewidth\":2}}},\"xaxis\":{\"anchor\":\"y\",\"domain\":[0.0,1.0],\"title\":{\"text\":\"Customer Id\"}},\"yaxis\":{\"anchor\":\"x\",\"domain\":[0.0,1.0],\"title\":{\"text\":\"Index\"}},\"legend\":{\"tracegroupgap\":0},\"title\":{\"text\":\"Customer Id by Index\"},\"barmode\":\"relative\",\"font\":{\"size\":12},\"margin\":{\"l\":50,\"r\":50,\"t\":50,\"b\":50}},                        {\"responsive\": true}                    ).then(function(){\n",
       "                            \n",
       "var gd = document.getElementById('364038f7-3893-411b-95a7-26a2fa25ab20');\n",
       "var x = new MutationObserver(function (mutations, observer) {{\n",
       "        var display = window.getComputedStyle(gd).display;\n",
       "        if (!display || display === 'none') {{\n",
       "            console.log([gd, 'removed!']);\n",
       "            Plotly.purge(gd);\n",
       "            observer.disconnect();\n",
       "        }}\n",
       "}});\n",
       "\n",
       "// Listen for the removal of the full notebook cells\n",
       "var notebookContainer = gd.closest('#notebook-container');\n",
       "if (notebookContainer) {{\n",
       "    x.observe(notebookContainer, {childList: true});\n",
       "}}\n",
       "\n",
       "// Listen for the clearing of the current output cell\n",
       "var outputEl = gd.closest('.output');\n",
       "if (outputEl) {{\n",
       "    x.observe(outputEl, {childList: true});\n",
       "}}\n",
       "\n",
       "                        })                };                            </script>        </div>\n",
       "</body>\n",
       "</html>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "�� Custom Analysis\n",
      "Available chart types: ['bar', 'line', 'scatter', 'histogram', 'box', 'pie', 'heatmap', 'area']\n",
      "Available columns: ['Index', 'Customer Id', 'First Name', 'Last Name', 'Company', 'City', 'Country', 'Phone 1', 'Phone 2', 'Email', 'Subscription Date', 'Website']\n",
      "\n",
      "📊 Example Custom Visualization:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<html>\n",
       "<head><meta charset=\"utf-8\" /></head>\n",
       "<body>\n",
       "    <div>            <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_SVG\"></script><script type=\"text/javascript\">if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}</script>                <script type=\"text/javascript\">window.PlotlyConfig = {MathJaxConfig: 'local'};</script>\n",
       "        <script charset=\"utf-8\" src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>                <div id=\"1e714819-9f29-4ad7-9c49-d4fa862e463a\" class=\"plotly-graph-div\" style=\"height:525px; width:100%;\"></div>            <script type=\"text/javascript\">                                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById(\"1e714819-9f29-4ad7-9c49-d4fa862e463a\")) {                    Plotly.newPlot(                        \"1e714819-9f29-4ad7-9c49-d4fa862e463a\",                        [{\"alignmentgroup\":\"True\",\"hovertemplate\":\"Index=%{y}\\u003cextra\\u003e\\u003c\\u002fextra\\u003e\",\"legendgroup\":\"\",\"marker\":{\"color\":\"#1f77b4\",\"pattern\":{\"shape\":\"\"}},\"name\":\"\",\"offsetgroup\":\"\",\"orientation\":\"v\",\"showlegend\":false,\"textposition\":\"auto\",\"x\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],\"xaxis\":\"x\",\"y\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],\"yaxis\":\"y\",\"type\":\"bar\"}],                        {\"template\":{\"data\":{\"barpolar\":[{\"marker\":{\"line\":{\"color\":\"white\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"barpolar\"}],\"bar\":[{\"error_x\":{\"color\":\"#2a3f5f\"},\"error_y\":{\"color\":\"#2a3f5f\"},\"marker\":{\"line\":{\"color\":\"white\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"bar\"}],\"carpet\":[{\"aaxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"#C8D4E3\",\"linecolor\":\"#C8D4E3\",\"minorgridcolor\":\"#C8D4E3\",\"startlinecolor\":\"#2a3f5f\"},\"baxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"#C8D4E3\",\"linecolor\":\"#C8D4E3\",\"minorgridcolor\":\"#C8D4E3\",\"startlinecolor\":\"#2a3f5f\"},\"type\":\"carpet\"}],\"choropleth\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"choropleth\"}],\"contourcarpet\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"contourcarpet\"}],\"contour\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"contour\"}],\"heatmapgl\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"heatmapgl\"}],\"heatmap\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"heatmap\"}],\"histogram2dcontour\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"histogram2dcontour\"}],\"histogram2d\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"histogram2d\"}],\"histogram\":[{\"marker\":{\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"histogram\"}],\"mesh3d\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"type\":\"mesh3d\"}],\"parcoords\":[{\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"parcoords\"}],\"pie\":[{\"automargin\":true,\"type\":\"pie\"}],\"scatter3d\":[{\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatter3d\"}],\"scattercarpet\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattercarpet\"}],\"scattergeo\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattergeo\"}],\"scattergl\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattergl\"}],\"scattermapbox\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scattermapbox\"}],\"scatterpolargl\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterpolargl\"}],\"scatterpolar\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterpolar\"}],\"scatter\":[{\"fillpattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2},\"type\":\"scatter\"}],\"scatterternary\":[{\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"type\":\"scatterternary\"}],\"surface\":[{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"type\":\"surface\"}],\"table\":[{\"cells\":{\"fill\":{\"color\":\"#EBF0F8\"},\"line\":{\"color\":\"white\"}},\"header\":{\"fill\":{\"color\":\"#C8D4E3\"},\"line\":{\"color\":\"white\"}},\"type\":\"table\"}]},\"layout\":{\"annotationdefaults\":{\"arrowcolor\":\"#2a3f5f\",\"arrowhead\":0,\"arrowwidth\":1},\"autotypenumbers\":\"strict\",\"coloraxis\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"colorscale\":{\"diverging\":[[0,\"#8e0152\"],[0.1,\"#c51b7d\"],[0.2,\"#de77ae\"],[0.3,\"#f1b6da\"],[0.4,\"#fde0ef\"],[0.5,\"#f7f7f7\"],[0.6,\"#e6f5d0\"],[0.7,\"#b8e186\"],[0.8,\"#7fbc41\"],[0.9,\"#4d9221\"],[1,\"#276419\"]],\"sequential\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"sequentialminus\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]},\"colorway\":[\"#636efa\",\"#EF553B\",\"#00cc96\",\"#ab63fa\",\"#FFA15A\",\"#19d3f3\",\"#FF6692\",\"#B6E880\",\"#FF97FF\",\"#FECB52\"],\"font\":{\"color\":\"#2a3f5f\"},\"geo\":{\"bgcolor\":\"white\",\"lakecolor\":\"white\",\"landcolor\":\"white\",\"showlakes\":true,\"showland\":true,\"subunitcolor\":\"#C8D4E3\"},\"hoverlabel\":{\"align\":\"left\"},\"hovermode\":\"closest\",\"mapbox\":{\"style\":\"light\"},\"paper_bgcolor\":\"white\",\"plot_bgcolor\":\"white\",\"polar\":{\"angularaxis\":{\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\"},\"bgcolor\":\"white\",\"radialaxis\":{\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\"}},\"scene\":{\"xaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"},\"yaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"},\"zaxis\":{\"backgroundcolor\":\"white\",\"gridcolor\":\"#DFE8F3\",\"gridwidth\":2,\"linecolor\":\"#EBF0F8\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"#EBF0F8\"}},\"shapedefaults\":{\"line\":{\"color\":\"#2a3f5f\"}},\"ternary\":{\"aaxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"},\"baxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"},\"bgcolor\":\"white\",\"caxis\":{\"gridcolor\":\"#DFE8F3\",\"linecolor\":\"#A2B1C6\",\"ticks\":\"\"}},\"title\":{\"x\":0.05},\"xaxis\":{\"automargin\":true,\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"#EBF0F8\",\"zerolinewidth\":2},\"yaxis\":{\"automargin\":true,\"gridcolor\":\"#EBF0F8\",\"linecolor\":\"#EBF0F8\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"#EBF0F8\",\"zerolinewidth\":2}}},\"xaxis\":{\"anchor\":\"y\",\"domain\":[0.0,1.0],\"title\":{\"text\":\"Index\"}},\"yaxis\":{\"anchor\":\"x\",\"domain\":[0.0,1.0],\"title\":{\"text\":\"Index\"}},\"legend\":{\"tracegroupgap\":0},\"title\":{\"text\":\"Example Bar Chart\"},\"barmode\":\"relative\",\"font\":{\"size\":12},\"margin\":{\"l\":50,\"r\":50,\"t\":50,\"b\":50}},                        {\"responsive\": true}                    ).then(function(){\n",
       "                            \n",
       "var gd = document.getElementById('1e714819-9f29-4ad7-9c49-d4fa862e463a');\n",
       "var x = new MutationObserver(function (mutations, observer) {{\n",
       "        var display = window.getComputedStyle(gd).display;\n",
       "        if (!display || display === 'none') {{\n",
       "            console.log([gd, 'removed!']);\n",
       "            Plotly.purge(gd);\n",
       "            observer.disconnect();\n",
       "        }}\n",
       "}});\n",
       "\n",
       "// Listen for the removal of the full notebook cells\n",
       "var notebookContainer = gd.closest('#notebook-container');\n",
       "if (notebookContainer) {{\n",
       "    x.observe(notebookContainer, {childList: true});\n",
       "}}\n",
       "\n",
       "// Listen for the clearing of the current output cell\n",
       "var outputEl = gd.closest('.output');\n",
       "if (outputEl) {{\n",
       "    x.observe(outputEl, {childList: true});\n",
       "}}\n",
       "\n",
       "                        })                };                            </script>        </div>\n",
       "</body>\n",
       "</html>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "🧪 Sample Data for Testing\n",
      "Generating sample sales data...\n",
      "✅ Sample data generated!\n",
      "📋 Sample Data Preview:\n",
      "        Date Region    Product  Sales  Quantity  Customer_Satisfaction\n",
      "0 2023-01-01   East  Product C   4627        98                   4.77\n",
      "1 2023-01-02   West  Product B   6450        34                   3.06\n",
      "2 2023-01-03  North  Product B   2663        27                   4.16\n",
      "3 2023-01-04   East  Product B   6592        91                   3.88\n",
      "4 2023-01-05   East  Product B   8392        75                   4.34\n",
      "5 2023-01-06   West  Product B   2306        63                   3.66\n",
      "6 2023-01-07  North  Product B   7776        44                   3.31\n",
      "7 2023-01-08  North  Product C   6864        89                   4.96\n",
      "8 2023-01-09   East  Product C   8526        70                   4.68\n",
      "9 2023-01-10  South  Product B   9901        50                   4.72\n",
      "\n",
      "==================================================\n",
      "�� Powered by AI Data Analysis Agent | Built with PraisonAI\n"
     ]
    }
   ],
   "source": [
    "# Main Application (Google Colab Version)\n",
    "import pandas as pd\n",
    "import plotly.express as px\n",
    "import numpy as np\n",
    "import tempfile\n",
    "import csv\n",
    "import json\n",
    "from typing import Dict, Any, List\n",
    "from google.colab import files\n",
    "import io\n",
    "\n",
    "# Initialize tools\n",
    "viz_tool = DataVisualizationTool()\n",
    "preprocess_tool = DataPreprocessingTool()\n",
    "stats_tool = StatisticalAnalysisTool()\n",
    "\n",
    "print(\"📊 AI Data Analysis Agent\")\n",
    "print(\"Intelligent data analysis powered by AI - Upload your data and ask questions in natural language!\")\n",
    "\n",
    "# File upload section for Google Colab\n",
    "print(\"\\n📁 Upload Your Data\")\n",
    "print(\"Please upload a CSV or Excel file:\")\n",
    "\n",
    "uploaded = files.upload()\n",
    "\n",
    "if uploaded:\n",
    "    # Get the first uploaded file\n",
    "    file_name = list(uploaded.keys())[0]\n",
    "    file_content = uploaded[file_name]\n",
    "\n",
    "    # Create a file-like object\n",
    "    file_obj = io.BytesIO(file_content)\n",
    "    file_obj.name = file_name\n",
    "\n",
    "    # Preprocess and save the uploaded file\n",
    "    temp_path, columns, df, error = preprocess_tool.preprocess_file(file_obj)\n",
    "\n",
    "    if error:\n",
    "        print(f\"❌ Error: {error}\")\n",
    "    elif temp_path and columns and df is not None:\n",
    "        # Display dataset information\n",
    "        print(f\"\\n📊 Dataset Information:\")\n",
    "        print(f\"- Rows: {len(df)}\")\n",
    "        print(f\"- Columns: {len(df.columns)}\")\n",
    "        print(f\"- Data Types: {len(df.dtypes.unique())}\")\n",
    "\n",
    "        # Data preview\n",
    "        print(f\"\\n📋 Data Preview:\")\n",
    "        print(df.head(10))\n",
    "\n",
    "        # Column information\n",
    "        print(f\"\\n�� Column Information:\")\n",
    "        col_info = pd.DataFrame({\n",
    "            'Column': df.columns,\n",
    "            'Data Type': df.dtypes.astype(str),\n",
    "            'Non-Null Count': df.count(),\n",
    "            'Null Count': df.isnull().sum(),\n",
    "            'Unique Values': df.nunique()\n",
    "        })\n",
    "        print(col_info)\n",
    "\n",
    "        # Analysis section\n",
    "        print(\"\\n🔍 Data Analysis\")\n",
    "        print(\"Available analysis options:\")\n",
    "        print(\"1. Quick Insights\")\n",
    "        print(\"2. Auto Visualizations\")\n",
    "        print(\"3. Custom Analysis\")\n",
    "\n",
    "        # Quick insights\n",
    "        print(\"\\n�� Quick Insights:\")\n",
    "        try:\n",
    "            # Comprehensive analysis\n",
    "            all_stats = {}\n",
    "            for analysis_type in ['descriptive', 'correlation', 'outliers']:\n",
    "                results = stats_tool.analyze_data(df, analysis_type)\n",
    "                all_stats[analysis_type] = results\n",
    "\n",
    "            # Display insights\n",
    "            if 'descriptive' in all_stats and 'info' in all_stats['descriptive']:\n",
    "                info = all_stats['descriptive']['info']\n",
    "                print(f\"📊 Dataset Overview:\")\n",
    "                print(f\"- Total records: {info['rows']}\")\n",
    "                print(f\"- Complete records: {info['rows'] - info['missing_values']}\")\n",
    "                print(f\"- Duplicate records: {info['duplicates']}\")\n",
    "                print(f\"- Missing values: {info['missing_values']}\")\n",
    "\n",
    "            # Outlier detection\n",
    "            if 'outliers' in all_stats and all_stats['outliers']:\n",
    "                print(f\"⚠️ Potential Outliers Detected:\")\n",
    "                for col, indices in all_stats['outliers'].items():\n",
    "                    print(f\"- {col}: {len(indices)} outliers\")\n",
    "\n",
    "            # High correlations\n",
    "            if 'correlation' in all_stats and 'high_correlations' in all_stats['correlation']:\n",
    "                high_corr = all_stats['correlation']['high_correlations']\n",
    "                if high_corr:\n",
    "                    print(f\"🔗 Strong Correlations:\")\n",
    "                    for var1, var2, corr in high_corr:\n",
    "                        print(f\"- {var1} ↔ {var2}: {corr:.3f}\")\n",
    "\n",
    "        except Exception as e:\n",
    "            print(f\"❌ Error generating insights: {str(e)}\")\n",
    "\n",
    "        # Auto visualization\n",
    "        print(\"\\n📈 Auto-Generated Visualizations:\")\n",
    "        try:\n",
    "            # Create multiple visualizations based on data types\n",
    "            numeric_cols = df.select_dtypes(include=[np.number]).columns\n",
    "            categorical_cols = df.select_dtypes(include=['object']).columns\n",
    "\n",
    "            if len(numeric_cols) > 0:\n",
    "                # Histogram for first numeric column\n",
    "                fig1 = viz_tool.create_visualization(\n",
    "                    df, 'histogram', numeric_cols[0],\n",
    "                    title=f\"Distribution of {numeric_cols[0]}\"\n",
    "                )\n",
    "                fig1.show()\n",
    "\n",
    "            if len(numeric_cols) > 1:\n",
    "                # Scatter plot for first two numeric columns\n",
    "                fig2 = viz_tool.create_visualization(\n",
    "                    df, 'scatter', numeric_cols[0], numeric_cols[1],\n",
    "                    title=f\"{numeric_cols[0]} vs {numeric_cols[1]}\"\n",
    "                )\n",
    "                fig2.show()\n",
    "\n",
    "            if len(categorical_cols) > 0 and len(numeric_cols) > 0:\n",
    "                # Bar chart for categorical vs numeric\n",
    "                fig3 = viz_tool.create_visualization(\n",
    "                    df, 'bar', categorical_cols[0], numeric_cols[0],\n",
    "                    title=f\"{categorical_cols[0]} by {numeric_cols[0]}\"\n",
    "                )\n",
    "                fig3.show()\n",
    "\n",
    "        except Exception as e:\n",
    "            print(f\"❌ Error creating visualizations: {str(e)}\")\n",
    "\n",
    "        # Custom analysis\n",
    "        print(\"\\n�� Custom Analysis\")\n",
    "        print(\"Available chart types:\", viz_tool.supported_charts)\n",
    "        print(\"Available columns:\", list(df.columns))\n",
    "\n",
    "        # Example custom visualization\n",
    "        if len(df.columns) > 1:\n",
    "            print(\"\\n📊 Example Custom Visualization:\")\n",
    "            chart_type = 'bar'\n",
    "            x_column = df.columns[0]\n",
    "            y_column = df.columns[1] if df.columns[1] in df.select_dtypes(include=[np.number]).columns else df.columns[0]\n",
    "\n",
    "            fig = viz_tool.create_visualization(\n",
    "                df, chart_type, x_column, y_column,\n",
    "                title=f\"Example {chart_type.title()} Chart\"\n",
    "            )\n",
    "            fig.show()\n",
    "\n",
    "else:\n",
    "    print(\"❌ No file uploaded. Please upload a CSV or Excel file.\")\n",
    "\n",
    "# Sample data section\n",
    "print(\"\\n🧪 Sample Data for Testing\")\n",
    "print(\"Generating sample sales data...\")\n",
    "\n",
    "# Generate sample data\n",
    "np.random.seed(42)\n",
    "sample_data = {\n",
    "    'Date': pd.date_range('2023-01-01', periods=100, freq='D'),\n",
    "    'Region': np.random.choice(['North', 'South', 'East', 'West'], 100),\n",
    "    'Product': np.random.choice(['Product A', 'Product B', 'Product C'], 100),\n",
    "    'Sales': np.random.randint(1000, 10000, 100),\n",
    "    'Quantity': np.random.randint(10, 100, 100),\n",
    "    'Customer_Satisfaction': np.random.uniform(3.0, 5.0, 100).round(2)\n",
    "}\n",
    "df_sample = pd.DataFrame(sample_data)\n",
    "\n",
    "print(\"✅ Sample data generated!\")\n",
    "print(\"📋 Sample Data Preview:\")\n",
    "print(df_sample.head(10))\n",
    "\n",
    "# Footer\n",
    "print(\"\\n\" + \"=\"*50)\n",
    "print(\"�� Powered by AI Data Analysis Agent | Built with PraisonAI\")"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
